Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte accuracy/difficulty dialog #287

Merged
merged 95 commits into from
Aug 31, 2021
Merged

Svelte accuracy/difficulty dialog #287

merged 95 commits into from
Aug 31, 2021

Conversation

SohumB
Copy link
Collaborator

@SohumB SohumB commented Aug 27, 2021

This branch is a rewrite of (and descendant from) #248.

The main user-facing elements of this branch are the new multi-targetting UI in acc_diff/ and slidinghud, and the reroll button on the top right of attack rolls. The main dev-facing element of the branch is the use of svelte for its components.

The branch still has an unused ReactiveForm in it — an abstract class that can handle reactive handlebars updates on arbitrary javascript data. But, Svelte broadly allows us to develop reactive UI, with components, without having to work around handlebars limitations.

The branch also has an unused SvelteApplication class in it as well — earlier versions of this branch used it, but now everything in this branch lives in the sliding HUD zone, which we mount directly without using a foundry class intermediary. Still, I can vouch for the pattern captured in that class; it should be useful and usable in the future, to add svelte to different leaf areas of the application.

Svelte needs to be informed whenever the backing data changes. The normal approach is to compute your dependent data within the svelte component; in which case the change notifications get fed through automatically. In the accdiff modal's case, since the backing data computes its own dependencies, we need to tell svelte about these dependency arrows:

$: aDoubled = a * 2 // javascript label syntax; svelte uses it to indicate computed properties
// @ts-ignore i.e., base depends on weapon
$: base = (weapon, base);
// @ts-ignore i.e., targets depend on weapon and base
$: targets = (weapon, base, targets);

Svelte also scopes css by default. That is, a css rule .foo { ... } means that svelte will output .foo.[autogeneratedid] { ... } and add that autogenerated class to every element in the same component it knows to have foo. The intent is that you can write per-component css without worrying about whether these class names are reused across the application. However, there are cases where you want to disable this behaviour. In our application, that means either adding those rules to lancer.scss, or using svelte's :global(...) selector — there's a few examples of the latter in this branch.

Svelte transitions are very slick, but there's some things to be aware of.

  • They only occur when the element actually enters or leaves the DOM, not when it's modified in place — in some cases that means wrapping the element with a {#key} block to destroy and recreate it.
  • In many cases, if you want an animation when an element is modified in place, a plain css animation will work.
  • During these transitions, two elements are then in the DOM at the same time. Thus, you may need to put a bit of work into ensuring they don't cause the underlying grid or flex to adjust their positions. The .grid-enforcement class in this branch is a first pass at that.
  • Destroying an element in one place and recreating "the same" element in a different place is handled with deferred transitions — crossfade. Crossfade is very powerful and a lot of patterns are very easy to animate with it, but like all powerful tools, it may behave in ways you don't expect if you don't fully understand it.
  • In general, applying more than one transition to the same event on visually equivalent elements will probably not behave how you want.
  • Svelte has a notion of a "local" transition — one that only occurs when the immediate parent scope is updated, but not on larger recreations of the whole tree. However, your modelling of this depends both on an understanding of svelte's notion of scopes, and an understanding of when your application is recreating the tree. Be careful.
  • Due to the very minimal runtime, Svelte-compiled code is eminently step-into-able and debuggable by hand.

@pyoner/svelte-types unfortunately exports the same type for both the class and the instance of a svelte component. Be careful about that.

We use vite-plugin-checker to provide typescript checking in a nice little window during the vite devserver, but it doesn't support svelte-check. I've included a personal copy of vite-plugin-checker that does (upstream PR at fi3ework/vite-plugin-checker#73), but it definitely has bugs. To disable it, comment out plugins.checker.svelte in vite.config.ts.

svelte-language-server is included in this PR and is what backs both npx svelte-check and the above checker plugin. You may wish to investigate integrating it with your IDE.

There's a few other things, but the Svelte API docs are comprehensive and excellent.

Miscellaneous other stuff that ended up getting stuffed into this branch

  • Dynamic imports to aid bundle splitting
  • Reroll buttons in chat messages for rerolling complex attacks
  • some slight updates to rollstring generation
  • some slight code simplification in the attack/tech attack macros
  • accdiff now has access to the tokens, potentially easing the way to checking token effects
  • accdiff form data is serializable, which we use with runEncodedMacro to remember selections in the form for the reroll
  • a bugfix on the .chat-button handler for runEncodedMacro logic such that the entire target can be clicked
  • rewriting runEncodedMacro to use a whitelist of allowed macros, instead of eval
  • buttons in chat, including the new reroll button, pulse for a few seconds on new chat messages; this is a hopefully subtle aid to discoverability.

Oh, and the AccDiff form now has a serializable plugin system, which in theory would allow third-parties to implement their own extensions to the window. Invisibility and Spotter are implemented using this system.

SohumB added 30 commits July 12, 2021 21:58
the only practical upshot of this collapse is that sometimes tech attacks
wouldn't expand to show some of the attack rolls. I've adjusted it to match
the regular attack rolls
+ take the opportunity to de-serialise operations a tiny bit
subtasks:
* separate out {{std-cover-input}} and {{accdiff-total-display}}
* rejigger accdiff's data model (again) (we use get total() functions now)
* messy UI work for the multi-target section of the acc_diff form
if/when we choose to extend lancer-actor-sheet's EncodedMacroHandler
to the whole app, we will be _ready_
we have basic checkbox UI for plugins, but not in the multi-target version of accdiff yet
Copy link
Owner

@Eranziel Eranziel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't finish now, so might as well submit these comments.

src/module/actor/lancer-actor.ts Outdated Show resolved Hide resolved
src/module/actor/lancer-actor.ts Outdated Show resolved Hide resolved
src/lancer.ts Show resolved Hide resolved
@Eranziel Eranziel merged commit a829e75 into Eranziel:dev-1.0 Aug 31, 2021
@SohumB SohumB deleted the svelte-accdiff branch August 31, 2021 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants